/* ======================================  Http  ====================================== */
import $fn from './fn'
import $config from './config'
// ======================================================== api
const api = $config.api[ $config.env ];
// ======================================================== 序列化对象
const serializeParam = (body) => {
    if (!$fn.hasObject(body)) return '';
    let param = body;
    let str = '';
    for (let i in param) {
        if ($fn.isValid(param[i])) { str += i + '=' + param[i] + '&' }
    }
    if (str.charAt(str.length - 1) === '&'){ str = str.slice(0, str.length - 1) }
    return encodeURI('?' + str);	// encodeURI 不对 [:, /, ;,?] 进行编码
}
const login = ()=>{
    wx.removeStorage({ key: 'user' });
    wx.removeStorage({ key: 'token' });
    wx.setStorageSync('loginPage', '/' + getCurrentPages()[0].route);
    setTimeout(() => {
        wx.redirectTo({ url: '/pages/login/index' });
    }, 1500)
}
const LogInfo = (method, api, param, data, index)=>{
	if($config.env){
		const colors = ['red', 'green', 'deepOrange']
		console.log(`%c ==================================【 ${method} 】【 ${api} 】==================================`, 'color:' + colors[index])
		console.log(' 参数：', param)
		console.log(' 数据：', data)
		console.log(`%c ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— end `, 'color:' + colors[index])
	}
}
const winHeight = wx.getSystemInfoSync().screenHeight;
// ======================================================== api
export default {
    http(url, param, opt){
        const userDefined = opt || {}
        let token = wx.getStorageSync('token') || ''
        let openId = $config.openId
        let action = opt.action || 'POST'
        let header = {}

        if (userDefined.isTokenOpenId){
            param = { ...param, openId }
            header = { Authorization: token }
        } else if (userDefined.isOpenId){
            param = { ...param, openId }
        }else{
            header =  opt.noToken ? {} : { Authorization: token }
        }

        const resApi = api + url + serializeParam(param);

        return new Promise((resolve, reject) => {
            wx.request({
                header: { ...header },
                method:action,
                url: resApi,
                success(res) {   
                    if (res.statusCode == 200){
                        let resData = res.data;
                        let code = resData.code;
                        let data = resData.data;
                        if (code === 200) {
                            resolve(data);
                            LogInfo(action, url, param, data, 1);
                        } else if (code === 201) {
                            wx.showToast({ title: '请先登录', icon: 'none' });
                            login()
                        } else if (code === 202) {
                            wx.showToast({ title: '登录过期，重新登录', icon: 'none' })
                            login()
                        } else {
                            wx.showToast({ title: resData['msg'], icon: 'none' })
                            userDefined.onError && userDefined.onError();
                            reject(resData)
                            LogInfo(action, url, param, resData, 2)
                        }
                    }else{
                        userDefined.onError && userDefined.onError();
                        wx.showToast({ title: '服务请求出错', icon: 'none' })
                        LogInfo(action, url, param, '无', 0)
                    }
                    userDefined.onAny && userDefined.onAny();
                },
                fail() {
                    wx.getNetworkType({
                        success(res) {
                            if (res.networkType === 'none') {
                                wx.showToast({ title: '无网络', icon: 'none' });
                                wx.stopPullDownRefresh();
                                wx.hideNavigationBarLoading();
                            } else {
                                wx.showToast({ title: '服务请求出错', icon: 'none' });
                            }
                        }
                    })
                    userDefined.onAny && userDefined.onAny();
                },
                complete(res) {
                    userDefined.onAny && userDefined.onAny();
                }
            })
        })
        
    },
    submit(_this, api, option){
        let opt = {
            param: {},
            loadingText:'数据提交中',                 // 加载提示文字
            succeedText: '',				// 自定义成功提示
            succeedFn: '',					// 成功之后执行
            errorText: '',					// 自定义错误提示
            submitLoading: 'submitLoading', // 加载判断
            replace: null,					// replace 路由
            push: null,						// push 路由
            reLaunch:null,                   // 跳转重载
            back: false,					// 是否后退
            refresh:false,                  // 刷新
            closeToast: false,				// 是否关闭默认提示
            anywayHandler: () => { },		// 无论请求成功或失败都执行此方法
            upload: false,					// 调用上传接口
            runFirst: false,				// 先跳转，后提示
            isOpenId: false,                 // 是以 openId 方式调用接口
            isTokenOpenId:false,            // token 与 openId 都必须传
            loading:true,                   //
            barLoading:false,
            successToast:''
        }
        Object.assign(opt, option || {});
        if(_this){
            opt.param = { ..._this.data.model, ...opt.param}
            _this.setData({ [opt.submitLoading]: true });
        }
        opt.loading && wx.showLoading({ title: opt.loadingText});
        opt.barLoading && wx.showNavigationBarLoading();

        const run = () => {
            opt.tab && wx.switchTab({ url: opt.tab });
            opt.replace && wx.redirectTo({ url: opt.replace });
            opt.push && wx.navigateTo({ url: opt.push });
            opt.reLaunch && wx.reLaunch({ url: opt.reLaunch });
            opt.back && wx.navigateBack();
            opt.refresh && _this.onRefresh();
            opt.succeedFn && opt.succeedFn();
        }

        return new Promise((resolve,reject) => {
            this.http(api, opt.param, {
                onAny: () => { 
                    _this&&_this.setData({ [opt.submitLoading]: false }); 
                    opt.onAny && opt.onAny(); 
                    opt.loading && wx.hideLoading();
                    opt.barLoading && wx.hideNavigationBarLoading();
                },
                upload: opt.upload,
                isOpenId: opt.isOpenId,
                hasTokenOpenId: opt.hasTokenOpenId,
                successToast: opt.successToast,
                _this,
            }).then(data => {
                resolve(data)
                // 提示后执行
                if (opt.succeedText) {
                    if (opt.runFirst) {
                        wx.showToast({ title: opt.succeedText, icon: 'success'})
                        run();
                    } else {
                        wx.showToast({ title: opt.succeedText, icon: 'success', success() { run() } })
                    }
                } else { // 直接执行
                    run();
                }
            }, data => {
                reject(data)
            })
        })
    },
    pull(_this, api, option){
        let opt = {
            dataName: 'data',				// 数据名字
            param: {},						// 参数
            pullLoading: 'pullLoading',		// 加载判断
            onError: () => { },
            loading:false,
            format:[],
            formatSplit:0,
            loading:true,
            barLoading: false,
            cutTitle:null,
            toArray:[]
        }
        Object.assign(opt, option || {});
     
        _this && _this.setData({ [opt.pullLoading]: true, refreshLoading:true });
        
        opt.loading && wx.showLoading({ title: '加载中...' });
        opt.barLoading && wx.showNavigationBarLoading();

        return new Promise((resolve, reject) => {
            this.http(api, opt.param, {
                onError: () => {
                    opt.onError();
                },
                onAny: () => {
                    _this && _this.setData({ [opt.pullLoading] : false });
                    opt.barLoading && wx.hideNavigationBarLoading();
                    wx.stopPullDownRefresh();
                    wx.hideNavigationBarLoading();
                    opt.loading && wx.hideLoading();
                    setTimeout(() => {
                        _this && _this.setData({ refreshLoading: false });
                    }, 500)
                },
                onError: () => {
                    _this && _this.setData({ [opt.pullLoading]: false });
                },
                _this,
                action:'GET'
            }).then(data => {
                if (opt.dataName !== null && opt.dataName !== '') {
                    _this&&_this.setData({ [opt.dataName]: data });
                }
                resolve(data);
            }, data => {
                reject(data)
            })
        })
    },
    paging(_this, api, option){
        let opt = {
            dataName: 'data',				    // 数据名字
            param: {},						    // 参数
            pageCurrent:'pageCurrent',          // 当前页
            pagingLoading: 'pagingLoading',		    // 加载判断
            loadingComplete: 'loadingComplete', // 加载完毕
            pager:'pager',                      // 
            loading: false,
            pageSize:10,
            format:[],
            id: '#scrollWraper',
            paging: 'paging'
        }

        Object.assign(opt, option || {});

        return new Promise((resolve,reject)=>{
            if (_this.data[opt.loadingComplete]) { resolve(_this.data.data); return; }
            
            wx.showLoading({ title: '加载中...' });
            _this.setData({ [opt.pagingLoading]: true, refreshLoading: true, [opt.loadingComplete]: false, [opt.pageCurrent]:_this.data[opt.pageCurrent] });
 
            this.http(api, { size: opt.pageSize, page: _this.data[opt.pageCurrent], ..._this.model, ...opt.param }, {
                onAny: () => {
                    wx.hideLoading();
                    wx.stopPullDownRefresh();
                    wx.hideNavigationBarLoading();
                    _this.setData({ [opt.pagingLoading]: false });
                    setTimeout(()=>{
                        _this.setData({ refreshLoading:false });
                    },500)
                },
                action:'GET'
            }).then(data => {
                let result = data.data;
                _this.setData({ [opt.pager]: { page: data.page, [opt.pageCurrent]: data.page, total: data.total_items } })
               
                resolve(result);

                wx.hideLoading();

                if (_this.data[opt.dataName] === result) { return; }

                _this.setData({ [opt.dataName]: _this.data[opt.dataName].concat(result), [opt.pageCurrent]: data.page + 1 })

                if (
                        ($fn.hasArray(_this.data[opt.dataName]) && _this.data[opt.dataName].length === data.total_items) || 
                        _this.data[opt.dataName].length === 0 ||
                        data.total_pages === 1
                    ) {
                    setTimeout(()=>{
                        _this.setData({ [opt.loadingComplete]: true })
                    })
                }
         
                // 检测分页数据是否触底
                wx.createSelectorQuery().select(opt.id).boundingClientRect(rect => {
                    if($fn.hasObject(rect)){
                        if (rect.height <= winHeight && !_this.data.loadingComplete) {
                            _this[opt.paging]();
                        }
                    }
                }).exec()
            },data=>{
                reject(data)
            })
        })
    },
    upload(sourceType, formData){
        let opt = {}
        let self = this;
        const token = wx.getStorageSync('token');
        const resApi = api + 'file/uploadOSS';
        return new Promise((resolve,reject)=>{
            wx.chooseImage({
                count: 1, // 默认9
                sizeType: ['original', 'compressed'],               // 可以指定是原图还是压缩图，默认二者都有
                sourceType: [sourceType],     // 可以指定来源是相册还是相机，默认二者都有 ['album', 'camera']
                success(res) {
                    res.tempFilePaths.forEach((v) => {
                        self.uploadFile(resApi, token, v, formData, data => {
                            resolve(data);
                        })
                    })
                }
            })
        })
    },
    uploadFile(api,token,filePath, formData, callback){
        wx.showLoading({ title: '上传图片中...' });
        wx.uploadFile({
            header: { 'Content-Type': 'multipart/form-data', UB_UserAgent_plat: 'WECHATM', UB_UserAgent_appUserAuthToken: token },
            url: api,
            filePath: filePath,
            name: 'Filedata',
            formData: formData || {},
            success: function (res) {
                if (res.statusCode == 200) {
                    let resData = JSON.parse(res.data);
                    let code = resData.status;
                    let data = resData.data;
                    if (code === 200) {
                        callback(data);
                    } else if (code ===201) {
                        wx.showToast({ title: resData['msg'], icon: 'none' })
                        setTimeout(() => {
                            wx.redirectTo({ url: '/pages/login/index' });
                        }, 1500)
                    } else if (code === 202) {
                        wx.showToast({ title: '请先登录', icon: 'none' })
                        wx.redirectTo({ url: '/pages/login/index' });
                    } else {
                        wx.showToast({ title: '上传失败', icon: 'none' })
                    }
                    wx.hideLoading();
                } else {
                    wx.showToast({ title: '服务请求出错', icon: 'none' })
                }
            },
            fail() {
                wx.getNetworkType({
                    success(res) {
                        if (res.networkType === 'none') {
                            wx.showToast({ title: '无网络', icon: 'none' })
                        } else {
                            wx.showToast({ title: '服务请求出错', icon: 'none' });
                        }
                    }
                })
                wx.hideLoading();
            }
        })
    }
}